#include <git2.h>
#include <stdio.h>
#include <string.h>

int main() {
	git_libgit2_init();
	char *repo_path = "test_repos";
	git_repository *repo;
	int i;
	char out[GIT_OID_HEXSZ+1];

	int error = git_repository_open(&repo ,repo_path);
	if(error<0) {
		printf("git_repository_open failed, error msg:%s\n", giterr_last()->message);
	}
	printf("open ok\n");

	//head
	git_reference *head;
	git_repository_head(&head, repo);

	const git_oid *oid = git_reference_target(head);
	if(oid == NULL) {
		printf("git_reference_target failed, code message:%s\n", giterr_last()->message);
		return -1;
	}
	// git_oid_fmt(out, oid);
	//printf("head reference target oid:%s\n", out);
	// printf("default branch:%s\n", git_reference_name(head));

	git_commit *commit;
	if(git_commit_lookup(&commit, repo, oid) < 0) {
		printf("git_commit_lookup failed, error code:%d, code message:%s\n", error, giterr_last()->message);
		return -1;
	}

	git_tree *tree = NULL;
	if(git_commit_tree(&tree, commit) < 0) {
		printf("git_commit_tree failed!\n");
		goto cleanup;
	}

	git_index *index = NULL;
	git_index_new(&index);
	if (git_index_read_tree(index, (const git_tree *)tree) < 0) {
		printf("read tree failed!\n");
		goto cleanup;
	}

	const char *content = "this is content!";
	git_index_entry entry;
	entry.mode = GIT_FILEMODE_BLOB;
	entry.path = "new_file";
	git_index_add_frombuffer(index, &entry, (const void *)content, strlen(content));
	git_oid new_tree_oid;
	if(git_index_write_tree_to(&new_tree_oid, index, repo) < 0) {
		printf("git_index_write_tree failed, error msg:%s\n", giterr_last()->message);
		goto cleanup;
	}
	bzero(out, GIT_OID_HEXSZ+1);
	git_oid_fmt(out, &new_tree_oid);
	printf("create tree oid:%s\n", out);
	git_object *new_tree = NULL;
	if(git_object_lookup(&new_tree, repo, &new_tree_oid, GIT_OBJ_TREE) < 0) {
		printf("git_object_lookup failed, error msg:%s\n", giterr_last()->message);
		goto cleanup;
	}
	const git_signature *author = git_commit_author(commit);
	git_oid new_cmt_oid;
	git_commit *parents[] = {commit};
	error = git_commit_create(
		&new_cmt_oid,
		repo,
		git_reference_name(head),
		author,
		author,
		NULL,
		"create commit",
		(git_tree *)new_tree,
		*parents == NULL ? 0 : 1,
		(const git_commit **) parents);

	if(error < 0) {
		printf("git_commit_create failed, error msg:%s\n", giterr_last()->message);
		goto cleanup;
	}
	printf("create commit successed!\n");
	git_oid_fmt(out, &new_cmt_oid);
	printf("create commit oid:%s\n", out);

	git_index_free(index);
	cleanup:
		git_tree_free(tree);
		git_commit_free(commit);
		git_reference_free(head);
		git_repository_free(repo);
	return 0;
}
